﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using MaxStoreErp.Core.Annotations;

namespace MaxStoreErp.Core.Infrastructure
{
    public class FixedStack<T> : IEnumerable, INotifyPropertyChanged
    {
        private readonly int _limit;
        private readonly LinkedList<T> _list;

        public FixedStack(int maxSize)
        {
            _limit = maxSize;
            _list = new LinkedList<T>();
        }

        public void Push(T value)
        {
            if (_list.Count == _limit)
                _list.RemoveLast();

            _list.AddFirst(value);
            OnPropertyChanged("Count");
        }

        public T Pop()
        {
            if (_list.Count <= 0)
                throw new InvalidOperationException("The Stack is empty");

            var value = _list.First.Value;
            _list.RemoveFirst();
            OnPropertyChanged("Count");
            return value;
        }

        public T Peek()
        {
            if (_list.Count <= 0)
                throw new InvalidOperationException("The Stack is empty");

            return _list.First.Value;
        }

        public void Clear()
        {
            _list.Clear();
            OnPropertyChanged("Count");
        }

        public int Count
        {
            get { return _list.Count; }
        }

        public bool IsTop(T value)
        {
            var result = false;
            if (Count > 0)
            {
                result = Peek().Equals(value);
            }
            return result;
        }

        public bool Contains(T value)
        {
            return Count != 0 && _list.Contains(value);
        }

        public IEnumerator GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
